package cn.tedu.charging.device.service.impl;

import cn.tedu.charging.device.dao.repository.StationRepository;
import cn.tedu.charging.device.pojo.po.StationPO;
import cn.tedu.charging.device.service.StationService;
import cn.tedu.common.pojo.vo.StationInfoVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.*;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.BoundGeoOperations;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

@Service
public class StationServiceImpl implements StationService {
    public static final String KEY_STATION_GEO = "stations_geo";
    private static final String KEY_STATIONS_DETAIL = "stations_detail";
    @Autowired
    private RedisTemplate redisTemplate; //这个对象的应用也可以封装到StationCacheRepository中

    @Autowired
    private StationRepository stationRepository;

    @Override
    public StationInfoVO getStationInfo(Integer id) {
        //1.从redis获取指定场站信息
        BoundHashOperations boundHashOperations =
                redisTemplate.boundHashOps(KEY_STATIONS_DETAIL);
        StationPO stationPO = (StationPO) boundHashOperations.get(String.valueOf(id));
        //2.如果不存在，则从数据库获取。
        if(stationPO==null){
            stationPO=stationRepository.selectStationById(id);
        }
        //3.如果存在，直接返回
        StationInfoVO stationInfoVO=new StationInfoVO();
        BeanUtils.copyProperties(stationPO,stationInfoVO);
        return stationInfoVO;
    }

    /**查询附近场站*/
    @Override
    public List<StationInfoVO> getNearStationList(Double longitude, Double latitude, Double radius) {
        //1.基于用户位置(经纬度和半径)绘制一个圆
        //1.1 创建一个圆心
        Point userPosition=new Point(longitude,latitude);
        //1.2 创建一个半径
        Distance distance=new Distance(radius, Metrics.KILOMETERS);
        //1.3 创建一个圆
        Circle circle=new Circle(userPosition,distance);

        //2.获取所有场站信息
        //2.1 构建一个BoundGeoOperations对象，应用操作Redis中的Geo类型数据
        BoundGeoOperations boundGeoOperations = redisTemplate.boundGeoOps(KEY_STATION_GEO);

        //2.2 查询在指定圆范围之内的所有场站
          RedisGeoCommands.GeoRadiusCommandArgs args =
                RedisGeoCommands.GeoRadiusCommandArgs.newGeoRadiusArgs()
                        .includeDistance() //是否包含距离
                        .includeCoordinates();//是否包含坐标
          GeoResults<RedisGeoCommands.GeoLocation<String>> geoResults =
                boundGeoOperations.radius(circle, args);

        //3.遍历所有附近场站，获取场站详情信息，并封装到StationInfoVO对象
        //3.1 获取操作站点详情信息的对象
        BoundHashOperations boundHashOperations = redisTemplate.boundHashOps(KEY_STATIONS_DETAIL);
        //3.2 遍历所有附近场站,并基于场站id获取场站详情
        Iterator<GeoResult<RedisGeoCommands.GeoLocation<String>>> iterator = geoResults.iterator();
        List<StationInfoVO> list=new ArrayList<>();
        while(iterator.hasNext()){
            GeoResult<RedisGeoCommands.GeoLocation<String>> next = iterator.next();
            //获取场站id和距离
            String id = next.getContent().getName();
            double distanceValue = next.getDistance().getValue();
            //基于场站id获取场站详情
            StationPO stationPO  =(StationPO) boundHashOperations.get(id);
            //构建一个StationInfoVO对象
            StationInfoVO stationInfoVO=new StationInfoVO();
            BeanUtils.copyProperties(stationPO,stationInfoVO);
            stationInfoVO.setDistance(distanceValue);
            list.add(stationInfoVO);
        }
        return list;
    }
}
